﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Collections;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;
namespace DarrenSoft.DataAccessLayer.Repositories
{
    using DarrenSoft.DataAccessLayer.Interfaces;
    using DarrenSoft.Domain.DomainBase;
    using DarrenSoft.Domain.Entities;
    using DarrenSoft.Domain.Extends;
    using DarrenSoft.Core.MyException;
    public class Repository<T> : IRepository<T> where T : Entity, new()
    {
        #region IRepository<T> Member
        protected string tableName;
        protected string primaryKey;
        public string PrimaryKey
        {
            get
            {
                return primaryKey;
            }
        }
        public string TableName
        {
            get
            {
                return tableName;
            }
        }
        protected string sortField = "ID";//排序字段
        public string SortField
        {
            get
            {
                return sortField;
            }
            set
            {
                sortField = value;
            }
        }

       
        /// <summary>
        /// 是否为降序
        /// </summary>
        public bool IsDescending
        {
            get { return isDescending; }
            set { isDescending = value; }
        }
        public bool IsExistKey(Hashtable recordTable)
        {
            SqlParameter[] param = new SqlParameter[recordTable.Count];
            IEnumerator eKeys = recordTable.Keys.GetEnumerator();

            string fields = "";// 字段名
            int i = 0;

            while (eKeys.MoveNext())
            {
                string field = eKeys.Current.ToString();
                fields += string.Format(" {0} = @{1} AND", field, field);

                string val = recordTable[eKeys.Current.ToString()].ToString();
                param[i] = new SqlParameter(string.Format("@{0}", field), val);

                i++;
            }

            fields = fields.Substring(0, fields.Length - 3);//除去最后的AND
            string sql = string.Format("SELECT COUNT(*) FROM {0} WHERE {1}", tableName, fields);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.AddRange(param);

            return Convert.ToInt32(db.ExecuteScalar(command)) > 0;
        }
        private bool isDescending = true;//
        protected string SelectedFields
        {
            get { return selectedFields; }
            set { selectedFields = value; }
        }
        protected string selectedFields = " * ";
        public Repository() { }
        public Repository(string tableName, string primaryKey) { this.tableName = tableName; this.primaryKey = primaryKey; }
        protected virtual Hashtable GetHashByEntity(T obj)
        {
            Hashtable ht = new Hashtable();
            PropertyInfo[] pis = obj.GetType().GetProperties();
            for (int i = 0; i < pis.Length; i++)
            {
                if (pis[i].Name != PrimaryKey)
                {
                    object objValue = pis[i].GetValue(obj, null);
                    objValue = (objValue == null) ? DBNull.Value : objValue;

                    if (!ht.ContainsKey(pis[i].Name))
                    {
                        ht.Add(pis[i].Name, objValue);
                    }
                }
            }
            return ht;
        }
        public int Insert(Hashtable recordField, string targetTable, DbTransaction trans)
        {
            int result = -1;
            string fields = ""; // 字段名
            string vals = ""; // 字段值
            if (recordField == null || recordField.Count < 1)
            {
                return result;
            }

            SqlParameter[] param = new SqlParameter[recordField.Count];
            IEnumerator eKeys = recordField.Keys.GetEnumerator();

            int i = 0;
            while (eKeys.MoveNext())
            {
                string field = eKeys.Current.ToString();
                fields += field + ",";
                vals += string.Format("@{0},", field);
                object val = recordField[eKeys.Current.ToString()];
                param[i] = new SqlParameter("@" + field, val);

                i++;
            }

            fields = fields.Trim(',');//除去前后的逗号
            vals = vals.Trim(',');//除去前后的逗号
            string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2});SELECT SCOPE_IDENTITY()", targetTable, fields, vals);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.AddRange(param);

            if (trans != null)
            {
                result = Convert.ToInt32(db.ExecuteScalar(command, trans).ToString());
            }
            else
            {
                result = Convert.ToInt32(db.ExecuteScalar(command).ToString());
            }

            return result;
        }

        public T Get(object id)
        {
            if (id == null) throw new ArgumentNullException("id");

            string sql = string.Format("Select {0} From {1} Where ({2} = @ID)", selectedFields, tableName, primaryKey);
            SqlParameter param = new SqlParameter("@ID", id);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.Add(param);

            T entity = null;
            using (IDataReader dr = db.ExecuteReader(command))
            {
                if (dr.Read())
                {
                    entity = DataReaderToEntity(dr);
                }
            }
            return entity;
        }
        protected virtual T DataReaderToEntity(IDataReader dr)
        {
            T obj = new T();
            PropertyInfo[] pis = obj.GetType().GetProperties();

            foreach (PropertyInfo pi in pis)
            {
                try
                {
                    if (dr[pi.Name].ToString() != "")
                    {
                        pi.SetValue(obj, dr[pi.Name] ?? "", null);
                    }
                }
                catch { }
            }
            return obj;
        }

        public object Insert(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");
            return Insert(GetHashByEntity(entity), this.TableName, null);
        }
        public bool Update(string id, Hashtable recordField, string targetTable, DbTransaction trans)
        {
            string field = ""; // 字段名
            object val = null; // 值
            string setValue = ""; // 更新Set () 中的语句

            if (recordField == null || recordField.Count < 1)
            {
                return false;
            }

            SqlParameter[] param = new SqlParameter[recordField.Count];
            int i = 0;

            IEnumerator eKeys = recordField.Keys.GetEnumerator();
            while (eKeys.MoveNext())
            {
                field = eKeys.Current.ToString();
                val = recordField[eKeys.Current.ToString()];
                val = val ?? DBNull.Value;
                if (val is DateTime)
                {
                    if (Convert.ToDateTime(val) <= Convert.ToDateTime("1753-1-1"))
                    {
                        val = DBNull.Value;
                    }
                }

                setValue += string.Format("[{0}] = @{0},", field);//加[ ]用来避免关键字错误
                param[i] = new SqlParameter(string.Format("@{0}", field), val);

                i++;
            }

            string sql = string.Format("UPDATE {0} SET {1} WHERE {2} = @ID ", targetTable, setValue.Substring(0, setValue.Length - 1), primaryKey);
            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.AddRange(param);

            if (!command.Parameters.Contains("@ID"))
            {
                SqlParameter paramPrimary = new SqlParameter("@ID", id);
                command.Parameters.Add(paramPrimary);
            }

            bool result = false;
            if (trans != null)
            {
                result = db.ExecuteNonQuery(command, trans) > 0;
            }
            else
            {
                result = db.ExecuteNonQuery(command) > 0;
            }

            return result;
        }
      
        public bool Update(T entity, string primaryKeyValue)
        {
            return Update(primaryKeyValue,GetHashByEntity(entity),this.TableName,null);
        }
        public void Delete(object id)
        {

            string condition = string.Format("{0} = @ID", primaryKey);
            SqlParameter paramPrimary = new SqlParameter("@ID", id);

             DeleteByCondition(condition, null, new SqlParameter[] { paramPrimary });

        }
      

        /// <summary>
        /// 根据指定对象的ID,从数据库中删除指定对象(用于整型主键)
        /// </summary>
        /// <param name="key">指定对象的ID</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public bool DeleteByKey(string key, DbTransaction trans)
        {
            string condition = string.Format("{0} = '{1}'", primaryKey, key);
            return DeleteByCondition(condition, trans);
        }

        /// <summary>
        /// 根据指定条件,从数据库中删除指定对象
        /// </summary>
        /// <param name="condition">删除记录的条件语句</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public bool DeleteByCondition(string condition)
        {
            return DeleteByCondition(condition, null);
        }

        /// <summary>
        /// 根据指定条件,从数据库中删除指定对象
        /// </summary>
        /// <param name="condition">删除记录的条件语句</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public bool DeleteByCondition(string condition, DbTransaction trans)
        {
            return DeleteByCondition(condition, trans, null);
        }

        /// <summary>
        /// 根据指定条件,从数据库中删除指定对象
        /// </summary>
        /// <param name="condition">删除记录的条件语句</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public bool DeleteByCondition(string condition, DbTransaction trans, IDbDataParameter[] paramList)
        {
            string sql = string.Format("DELETE FROM {0} WHERE {1} ", tableName, condition);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            if (paramList != null)
            {
                command.Parameters.AddRange(paramList);
            }

            bool result = false;
            if (trans != null)
            {
                result = db.ExecuteNonQuery(command, trans) > 0;
            }
            else
            {
                result = db.ExecuteNonQuery(command) > 0;
            }

            return result;
        }
               		
        public IList<T> GetAll()
        {
            string sql = string.Format("Select {0} From {1}", selectedFields, tableName);
            sql += string.Format(" Order by {0} {1}", sortField, isDescending ? "DESC" : "ASC");

            List<T> list = GetList(sql, null);
            return list;

        }
        private List<T> GetList(string sql, IDbDataParameter[] paramList)
        {
            T entity = null;
            List<T> list = new List<T>();

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            if (paramList != null)
            {
                command.Parameters.AddRange(paramList);
            }

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    entity = DataReaderToEntity(dr);

                    list.Add(entity);
                }
            }
            return list;
        }
        public List<T> Find(out int recordsCount,string condition, PagerBase info)
        {
            List<T> list = new List<T>();

            Database db = DatabaseFactory.CreateDatabase();

            PagerHelper helper = new PagerHelper(tableName, condition);
            info.RecordsCount = helper.GetCount();
            recordsCount = info.RecordsCount;
            PagerHelper helper2 = new PagerHelper(tableName, false, selectedFields /*" * "*/, sortField,
                info.PageSize, info.PageIndex, isDescending, condition);

            using (IDataReader dr = helper2.GetDataReader())
            {
                while (dr.Read())
                {
                    list.Add(this.DataReaderToEntity(dr));
                }
            }
            return list;
        }
        #endregion
    }
}
